class_name GameplayState
extends Node
## Gameplay State
## Version: 0.1.0

##
var _transitions: Array[GameplayStateTransition] = []


func change_state(target_state_name: String, on_transit: Callable) -> bool:
	var state_machine = get_parent() as GameplayStateMachine
	assert(state_machine, "State machine should not be null!")

	assert(state_machine._states.has(target_state_name), "Target state do not have the same state machine of this state!")
	assert(target_state_name != "AnyState", "Can not change to AnyState!")

	if target_state_name == state_machine._current_state_name:
		return false

	state_machine._states[state_machine._current_state_name].on_exit()
	state_machine._current_state_name = target_state_name
	on_transit.call()
	state_machine._states[target_state_name].on_enter()

	return true


func on_setup() -> void:
	_on_setup()


func on_enter() -> void:
	if name == "GhostState":
		assert(try_all_transitions() or get_parent()._states["AnyState"].try_all_transitions(), "GhostState must be exited!")
		return

	_on_enter()


func try_all_transitions() -> bool:
	for transition: GameplayStateTransition in _transitions:
		if transition.try_condition() and change_state(transition.try_transition(), transition.on_transit):
			return true

	return false


func on_update(_delta: float) -> void:
	if not try_all_transitions():
		_on_update(_delta)


func on_exit() -> void:
	_on_exit()


#region Need to override
func _on_setup() -> void:
	pass


func _on_enter() -> void:
	pass


func _on_update(_delta: float) -> void:
	pass


func _on_exit() -> void:
	pass
#endregion
